using JNPF.Extensions.ServiceExtensions;
using JNPF.IMServe;
using JNPF.Utils;
using JNPF.Utils.Controller;
using JNPF.Utils.DB;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Senparc.CO2NET;
using Senparc.CO2NET.RegisterServices;
using Senparc.Weixin;
using Senparc.Weixin.Entities;
using Senparc.Weixin.RegisterServices;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;

namespace JNPF.Api
{
    /// <summary>
    /// Startup
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// configuration
        /// </summary>
        public IConfiguration Configuration { get; }
        /// <summary>
        /// Startup
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            ConfigurationHelper.Configuration = configuration;
        }
        /// <summary>
        /// ConfigureServices
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(new Appsettings(Configuration));


            services.AddJobSetup();
            #region 跨域配置
            services.AddCors(options =>
            {
                var origins = Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(',');
                options.AddPolicy("jnpfCors", policy => policy.WithOrigins(origins).AllowAnyHeader().AllowAnyMethod().AllowCredentials());
            });
            #endregion

            
            #region Swagger基础配置
            services.AddSwaggerGen(option =>
            {
                //接口文档名称
                option.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version = "v1",
                    Title = Appsettings.app(new string[] { "Startup", "ApiName" }) + " - 接口API文档"
                });

                var dir = new DirectoryInfo(AppContext.BaseDirectory);
                foreach (FileInfo file in dir.EnumerateFiles("*.xml"))
                {
                    option.IncludeXmlComments(file.FullName);
                }
                //添加Authorization
                option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "在下框中输入请求头中需要添加Jwt授权Token：Bearer Token",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Scheme = "bearer",
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT"
                });
                option.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference(){ Id="Bearer",Type=ReferenceType.SecurityScheme }
                        },
                        Array.Empty<string>()
                    }
                });
            });
            #endregion

            services.AddMvc(options =>
            {
                options.EnableEndpointRouting = false;
            });
            //文件大小问题
            services.Configure<FormOptions>(options =>
            {
                // Set the limit to 256 MB
                options.MultipartBodyLengthLimit = int.MaxValue;
            });
            services.AddControllers(options =>
            {
                options.Filters.Add<FilterLogin>();
                options.Filters.Add<FilterException>();
                options.Filters.Add<FilterRequest>();
            })
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                //options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
                //options.SerializerSettings.Converters.Add(new UnixTimeStampConverter());
            });
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            services.AddAuthentication_JWTSetup();

            #region 微信
            services.AddSenparcGlobalServices(Configuration)//Senparc.CO2NET 全局注册
                        .AddSenparcWeixinServices(Configuration);//Senparc.Weixin 注册（如果使用Senparc.Weixin SDK则添加）
            services.AddSession();
            services.AddMemoryCache();//使用本地缓存必须添加
            services.AddSenparcWeixinServices(Configuration);
            #endregion

            #region 任务调度
            //services.AddSingleton<IJobFactory, QuartzFactory>();
            //services.AddSingleton<ISchedulerCenter, SchedulerCenterServer>();
            //services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
            #endregion
        }

        /// <summary>
        /// Configure
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        /// <param name="senparcSetting"></param>
        /// <param name="senparcWeixinSetting"></param>
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting, Microsoft.AspNetCore.Hosting.IApplicationLifetime appLifeTime)
        {
            #region 静态文件
            app.UseStaticFiles();
            String codeGeneratePath = Path.Combine(Directory.GetCurrentDirectory(), "CodeGenerate");
            FileHelper.CreateDir(codeGeneratePath);
            //启用静态资源(无参默认wwwroot文件夹)
            app.UseStaticFiles(new StaticFileOptions
            {
                //资源所在的绝对路径。
                FileProvider = new PhysicalFileProvider(codeGeneratePath),
                //表示访问路径,必须'/'开头
                RequestPath = "/CodeGenerate"
            });
           
            #endregion

            #region HttpContext
            Utils.HttpContext.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());
            #endregion

            #region Swagger
            app.UseSwagger();
            app.UseSwaggerUI(option =>
            {
                option.SwaggerEndpoint("/swagger/v1/swagger.json", "JNPF软件开发平台 - 接口API文档");
                option.RoutePrefix = "swagger";
                option.DocumentTitle = "JNPF API";
            });
            #endregion

            #region WebSocket
            var webSocketOptions = new WebSocketOptions()
            {
                KeepAliveInterval = TimeSpan.FromSeconds(20),
                ReceiveBufferSize = 4 * 1024
            };
            app.UseWebSockets(webSocketOptions);
            app.MapWebSocketManager("/websocket");
            #endregion

            //设置CultureInfo
            var zh = new CultureInfo("zh-CN");
            zh.DateTimeFormat.FullDateTimePattern = "yyyy-MM-dd HH:mm:ss";
            zh.DateTimeFormat.LongDatePattern = "yyyy-MM-dd";
            zh.DateTimeFormat.LongTimePattern = "HH:mm:ss";
            zh.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd";
            zh.DateTimeFormat.ShortTimePattern = "HH:mm:ss";
            IList<CultureInfo> supportedCultures = new List<CultureInfo>
            {
                zh,
            };
            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("zh-CN"),
                SupportedCultures = supportedCultures,
                SupportedUICultures = supportedCultures
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseCors("jnpfCors");
            app.UseAuthentication();
            app.UseAuthorization();
            //app.UseEndpoints(endpoints =>
            //{
            //    endpoints.MapControllers();
            //});
            // 开启QuartzNetJob调度服务
            //TimeTaskIService timeTaskIService = new TimeTaskService();
            //CronUtil cronUtil = new CronUtil();
            //app.UseQuartzJobMildd(timeTaskIService, cronUtil);
            //var quartz = app.ApplicationServices.GetRequiredService<SchedulerCenterServer>();
            //appLifeTime.ApplicationStarted.Register(()=>quartz.StartScheduleAsync().Wait());
            //appLifeTime.ApplicationStopped.Register(() => quartz.StopScheduleAsync().Wait());
            app.UseMvc();
            //app.UseWebSockets();
            //app.MapWebSocketManager("/websocket");


            IRegisterService register = RegisterService.Start(senparcSetting.Value).UseSenparcGlobal();//启动 CO2NET 全局注册，必须！
            register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value);//微信全局注册,必须！
        }
    }
}
